using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Security;
using System.Runtime.Serialization;
using TST.SharePoint.Shared;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using TST.SharePoint.Shared.WebControls;
using TST.WebParts.Shared.WebControls;

namespace TST.WebParts
{
    /// <summary>
    /// WebPart that displays data from numerous data sources in a grid.
    /// WebPart is built as ASP.NET webpart, but targeted at the WSS/MOSS platform.
    /// </summary>
    [ToolboxData("<{0}:ContentBySearch runat=server></{0}:ContentBySearch>")]
    public class ContentByTypeWebPart : BaseDataWebPart, IWebEditable
    {
        private SharePointGrid _grid;
        private SharePointCalendar _calendar;
        private SharePointGantt _gantt;
        private MenuTemplate itemMenu;
        private ObjectDataSource _filterableDatasource;

        /// <summary>
        /// Construction.
        /// </summary>
        public ContentByTypeWebPart() : base()
        {
            // Load available datasources.
            LoadDatasources();
        }

        /// <summary>
        /// Load licensed datasources.
        /// </summary>
        private void LoadDatasources()
        {
            this.DataSources.Add(new DatasourceContentType());
        }

        protected override void ConfigurationChanged()
        {
            if (_grid == null)
                return;
            _grid.GridDatasource = CurrentDataSource;
            _grid.Configuration = CurrentConfiguration;
        }

        public System.Data.DataTable SelectData()
        {
            if (CurrentDataSource != null)
            {
                if (_grid.FilterProviders.Count > 0 && CurrentConfiguration.Filters.Count == 0)
                {
                    _grid.SetFilters();
                }
                if (!CurrentConfiguration.JustSearchOnQuery || _grid.HasQuery)
                {
                    return CurrentDataSource.GetData();
                }
            }
            return null;
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            // Read datasource options for the current selected datasource
            SetCurrentDataSource();

            switch (CurrentConfiguration.GridType)
            {
                case DatasourceConfiguration.GridTypes.SharePointGrid:
                    _grid = new SharePointGrid(CurrentDataSource, CurrentConfiguration);
                    _grid.ID = String.Format("CBTGrid_{0}", this.ID);

                    // Add controls for filtering
                    _filterableDatasource = new ObjectDataSource();
                    _filterableDatasource.ID = String.Format("CBTDataSource_{0}", this.ID);
                    this.Controls.Add(_filterableDatasource);
                    SPGridViewPager pager = new SPGridViewPager();
                    pager.ID = String.Format("CBTPager_{0}", this.ID);
                    pager.GridViewId = _grid.ID;
                    Controls.Add(pager);
                    if (!CurrentConfiguration.CustomPaging)
                    {
                        _filterableDatasource.SelectMethod = "SelectData";
                        _filterableDatasource.TypeName = this.GetType().AssemblyQualifiedName;
                        _filterableDatasource.ObjectCreating += new ObjectDataSourceObjectEventHandler(_filterableDatasource_ObjectCreating);

                        _grid.DataSourceID = _filterableDatasource.ID;
                        _grid.EnableViewState = true;

                        _grid.FilteredDataSourcePropertyFormat = "{1} = '{0}'";
                        _grid.Sorting += new GridViewSortEventHandler(_grid_Sorting);
                        _filterableDatasource.Filtering += new ObjectDataSourceFilteringEventHandler(_filterableDatasource_Filtering);

                        pager.Visible = true;
                    }
                    else
                    {
                        pager.Visible = false;
                        _grid.PagerTemplate = null;
                    }

                    // Setup the menu template.
                    itemMenu = new MenuTemplate();
                    //itemMenu.ID = "ItemMenu";

                    string urlStart = SPContext.Current.Site.ServerRelativeUrl;
                    if (urlStart == "/")
                        urlStart = string.Empty;

                    // Add a menu item to navigate to the site that holds the item.
                    if (CurrentConfiguration.ShowWebMenuLink)
                    {
                        MenuItemTemplate webMenu = new MenuItemTemplate("Navigate to site", "/_layouts/images/stsicon.gif");
                        webMenu.ClientOnClickNavigateUrl = string.Format("{0}/_layouts/tst/tstredirect.aspx?WebId=%webid%&SiteId=%siteid%", urlStart);
                        webMenu.Attributes.Add("target", "_blank");
                        itemMenu.Controls.Add(webMenu);
                    }

                    // Add a menu item to navigate to the list that holds the item.
                    if (CurrentConfiguration.ShowListMenuLink)
                    {
                        MenuItemTemplate listMenu = new MenuItemTemplate("Navigate to list", "/_layouts/images/itdl.gif");
                        listMenu.ClientOnClickNavigateUrl = string.Format("{0}/_layouts/tst/tstredirect.aspx?WebId=%webid%&SiteId=%siteid%&ListId=%listid%", urlStart);
                        itemMenu.Controls.Add(listMenu);
                    }

                    // Add a menu item to navigate to the folder that holds the item.
                    if (CurrentConfiguration.ShowListFolderLink)
                    {
                        MenuItemTemplate listMenu = new MenuItemTemplate("Navigate to folder", "/_layouts/images/FOLDER16.GIF");
                        listMenu.ClientOnClickNavigateUrl = string.Format("{0}/_layouts/tst/tstredirect.aspx?WebId=%webid%&SiteId=%siteid%&ListId=%listid%&ItemId=%id%&Folder=1", urlStart);
                        itemMenu.Controls.Add(listMenu);
                    }

                    // Add a menu item to navigate to the list that holds the item.
                    if (CurrentConfiguration.ShowItemMenuLink)
                    {
                        MenuItemTemplate listItemMenu = new MenuItemTemplate("Navigate to item", "/_layouts/images/reorder.gif");
                        listItemMenu.ClientOnClickNavigateUrl = string.Format("{0}/_layouts/CopyUtil.aspx?Use=id&Action=dispform&ItemId=%id%&ListId=%listid%&WebId=%webid%&SiteId=%siteid%&Source=" + this.Page.Request.Url.AbsolutePath, urlStart);
                        itemMenu.Controls.Add(listItemMenu);
                    }

                    // Add menu template to the controls collection of the webpart.
                    this.Controls.Add(itemMenu);

                    Controls.Add(_grid);
                    break;
                case DatasourceConfiguration.GridTypes.SharePointCalendar:
                    _calendar = new SharePointCalendar(CurrentDataSource, CurrentConfiguration);
                    Controls.Add(_calendar);
                    break;
                case DatasourceConfiguration.GridTypes.SharePointGantt:
                    _gantt = new SharePointGantt(CurrentDataSource, CurrentConfiguration);
                    Controls.Add(_gantt);
                    break;
            }
        }


        protected sealed override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            if (Context.Request.Form["__EVENTARGUMENT"] != null &&
                 Context.Request.Form["__EVENTARGUMENT"].EndsWith("__ClearFilter__"))
            {
                // Clear FilterExpression
                ViewState.Remove("FilterExpression");
            }
        }

        private void SetUserFilter()
        {
            if (ViewState["FilterExpression"] != null)
            {
                String filter = (string)ViewState["FilterExpression"];
                if (String.IsNullOrEmpty(_filterableDatasource.FilterExpression))
                {
                    _filterableDatasource.FilterExpression = filter;
                }
            }
        }

        private void _grid_Sorting(object sender, GridViewSortEventArgs e)
        {
            SetUserFilter();
        }

        private void _filterableDatasource_Filtering(object sender, ObjectDataSourceFilteringEventArgs e)
        {
            ViewState["FilterExpression"] = ((ObjectDataSourceView)sender).FilterExpression;
        }

        private void _filterableDatasource_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
        {
            e.ObjectInstance = this;
        }

        #region IWebEditable Members

        /// <summary>
        /// Create the Editor parts for this webpart.
        /// </summary>
        /// <returns></returns>
        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            List<EditorPart> editors = new List<EditorPart>();

            EditorPartCollection baseParts = base.CreateEditorParts();
            foreach (EditorPart basePart in baseParts)
                editors.Add(basePart);

            editors.Add(new ContentByTypeEditorPart(this.ID));
            //editors.Add(new EditorDatasourceOptions(this.ID));

            // Make sure the current datasource is initialized correctly.
            SetCurrentDataSource();

            //if (CurrentDataSource != null)
            //{
            //    // Add the editor part for selecting and configuring fields.
            //    editors.Add(new EditorFields());
            //}

            // return the new collection.
            return new EditorPartCollection(editors);
        }

        object IWebEditable.WebBrowsableObject
        {
            get { return this; }
        }

        #endregion

        /// <summary>
        /// Javascript code to collapse nodes by default
        /// </summary>
        private const string EmbeddedScriptCollapseGrid = @"

    <script type=""text/javascript"">
    //<![CDATA[ 
    var GridNode = document.getElementById('{0}');
    var rows = GridNode.getElementsByTagName('tr');
    var numRows = rows.length;
    for (var i = 0; i < numRows; ++i) 
    {
        if (rows[i].getAttribute(""isexp"") != null && rows[i].getAttribute(""isexp"").toLowerCase() == ""true"")
            { 
                if(rows[i].firstChild.firstChild != null && rows[i].firstChild.firstChild.tagName.toLowerCase() == ""a"")
                {
                        rows[i].firstChild.firstChild.fireEvent(""onclick"");
                }
            }
     }
     //]]> 
     </script> ";

        /// <summary>
        /// Overriden for show correctly different content menu in a page with various webparts
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (_grid != null)
            {
                itemMenu.ID = this._grid.ClientID + "_ItemMenu";
                if (!CurrentConfiguration.CustomPaging)
                {
                    if (!CurrentConfiguration.JustSearchOnQuery || _grid.HasQuery)
                    {
                        SetUserFilter();
                        _grid.DataBind();
                    }
                }
            }
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            base.RenderContents(writer);

            //render collapse/expanded javascript, to the end of the page
            if (CurrentConfiguration != null && CurrentDataSource != null)
            {
                if ((CurrentConfiguration.GroupMode == "Collapsed") && (CurrentConfiguration.GroupBy != String.Empty))
                {
                    this.Page.ClientScript.RegisterStartupScript(this.GetType(), "CollapseGrid" + this.ClientID, EmbeddedScriptCollapseGrid.Replace("{0}", this.ClientID));
                }

            }

            if (CurrentConfiguration == null || CurrentDataSource == null)
            {
                writer.WriteLine(GetOpenToolPaneText("This webpart is not yet configured", this.ID));
            }
            else if (CurrentConfiguration.Fields.Count==0)
            {
                writer.WriteLine(GetOpenToolPaneText("No fields selected in the configuration editor", this.ID));
            }
            else if (CurrentConfiguration.JustSearchOnQuery)
            {
                if (_grid != null && !FilterAvailable(_grid.FilterProviders))
                {
                    writer.WriteLine(string.Format("Please select a filter value to display items in a list."));
                }
                else if (_calendar != null && !FilterAvailable(_calendar.FilterProviders))
                {
                    writer.WriteLine(string.Format("Please select a filter value to display items in a calendar."));
                }
            }

            if (CurrentConfiguration!=null && 
                CurrentConfiguration.CustomProperties.Contains("debug") && 
                CurrentDataSource!=null &&
                CurrentConfiguration.CustomProperties["debug"].Value=="true")
            {
                for (int i = 0; i < CurrentDataSource.QueryDebug.Count; i++)
                {
                    writer.WriteLine(string.Format("{0}<br>", Page.Server.HtmlEncode(CurrentDataSource.QueryDebug[i])));
                }
            }
        }

        private bool FilterAvailable(List<IFilterValues> list)
        {
            foreach (IFilterValues filter in list)
            {
                if (filter.ParameterValues != null)
                {
                    foreach (string val in filter.ParameterValues)
                    {
                        if (!string.IsNullOrEmpty(val))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        [ConnectionConsumer("filter", "IFilterValues", AllowsMultipleConnections = true)]
        public void SetFilter(IFilterValues filterValues)
        {
            if (filterValues != null)
            {
                EnsureChildControls();
                List<ConsumerParameter> parameters = new List<ConsumerParameter>();
                if (CurrentDataSource != null)
                {
                    foreach (Field field in CurrentDataSource.Fields)
                    {
                        if (field.FilterType != FilterType.Unknown)
                        {
                            parameters.Add(new ConsumerParameter(field.DisplayName, ConsumerParameterCapabilities.SupportsMultipleValues | ConsumerParameterCapabilities.SupportsEmptyValue | ConsumerParameterCapabilities.SupportsAllValue | ConsumerParameterCapabilities.SupportsEmptyValue));
                        }
                    }
                }
                filterValues.SetConsumerParameters(new System.Collections.ObjectModel.ReadOnlyCollection<ConsumerParameter>(parameters));
                if (_grid != null)
                {
                    _grid.FilterProviders.Add(filterValues);
                }
                if (_calendar != null)
                {
                    _calendar.FilterProviders.Add(filterValues);
                }
            }
        }

    }

}
